package net.freebytes.es.demo.controller;

import net.freebytes.es.common.repository.ESTemplate;
import net.freebytes.es.common.repository.PageList;
import net.freebytes.es.common.repository.Sort;
import net.freebytes.es.common.util.LambdaUtils;
import net.freebytes.es.common.util.QueryBuildersWrapper;
import net.freebytes.es.demo.entity.Account;
import net.freebytes.es.demo.service.BaseQueryService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@RestController
public class TestController {

    @Autowired
    private ESTemplate esTemplate;
    @Autowired
    private BaseQueryService queryService;

    @PostMapping("/save")
    public boolean save(Account account) {
        account.setCreateTime(LocalDateTime.now());
        return esTemplate.save(account);
    }

    @PostMapping("/update")
    public boolean update(Account account) {
        return esTemplate.update(account);
    }

    @GetMapping("/delete")
    public boolean delete(String id) {
        return esTemplate.deleteById(id, Account.class);
    }

    @GetMapping("/get")
    public Account get(String id) {
        return (Account) esTemplate.getById(id, Account.class);
    }

    /**
     * 模糊查询  es查询list会默认分页  默认10条一页
     *
     * @param keyword
     * @return
     */
    @GetMapping("/list")
    public List<Account> list(String keyword) {
        //复合查询
        BoolQueryBuilder boolQuery = QueryBuildersWrapper.boolQuery();
        //子查询
        BoolQueryBuilder subBool = QueryBuildersWrapper.boolQuery();
        //查询身份证或者交易账号为keyword的记录   (should  相当于 ‘or ’ 的意思)
        subBool.should(QueryBuildersWrapper.wildcardQuery(Account::getIdCard, "*" + keyword + "*"));
        subBool.should(QueryBuildersWrapper.wildcardQuery(Account::getTradingAccount, "*" + keyword + "*"));

        boolQuery.must(subBool);
        //查询身份证必不为空的记录       (must  相当于 ‘and ’ 的意思)
        boolQuery.must(QueryBuildersWrapper.existsQuery(Account::getIdCard));

        List<Account> accounts = esTemplate.search(boolQuery, Account.class);
        return accounts;
    }

    /**
     * 模糊查询  一次性返回所有数据
     *
     * @param keyword
     * @return
     */
    @GetMapping("/searchAfter")
    public List<Account> searchAfter(String keyword) {
        //复合查询
        BoolQueryBuilder boolQuery = QueryBuildersWrapper.boolQuery();
        //子查询
        BoolQueryBuilder subBool = QueryBuildersWrapper.boolQuery();
        //查询身份证或者交易账号为keyword的记录   (should  相当于 ‘or ’ 的意思)
        if (!StringUtils.isEmpty(keyword)) {
            subBool.should(QueryBuildersWrapper.wildcardQuery(Account::getIdCard, "*" + keyword + "*"));
            subBool.should(QueryBuildersWrapper.wildcardQuery(Account::getTradingAccount, "*" + keyword + "*"));
        }

        boolQuery.must(subBool);
        //查询身份证必不为空的记录       (must  相当于 ‘and ’ 的意思)
        boolQuery.must(QueryBuildersWrapper.existsQuery(Account::getIdCard));

        List<Account> list = queryService.searchAfter(boolQuery, new Sort(new Sort.Order(SortOrder.DESC, LambdaUtils.getName(Account::getCreateTime))), Account.class, new String[]{"id", "idCard", "tradingAccount"});

        return list;
    }


    /**
     * 在searchAfter的过程中，一边修改，看是否会影响查询结果
     * 结果 ，不会
     *
     * @return
     */
    @GetMapping("/searchAfterOnUpdate")
    public List<Account> searchAfterOnUpdate() {
        //复合查询
        BoolQueryBuilder boolQuery = QueryBuildersWrapper.boolQuery();
        //查询身份证必不为空的记录       (must  相当于 ‘and ’ 的意思)
        boolQuery.mustNot(QueryBuildersWrapper.existsQuery(Account::getIdCard));

        PageList<Account> page = queryService.searchAfterOnePage(boolQuery, Account.class, null);
        List<Account> list = new ArrayList<>();

        List<Account> accounts = page.getList();
        while (accounts != null && accounts.size() > 0) {

            for (Account account : accounts) {
                account.setIdCard(UUID.randomUUID().toString());
                esTemplate.update(account);
            }
            list.addAll(accounts);
            page = queryService.searchAfterOnePage(boolQuery, Account.class, page);
            if (page.getList() == null || page.getList().size() == 0) {
                break;
            }
            accounts = page.getList();
        }

        return list;
    }
}
